﻿#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include <vector>

using namespace std;

//class Person
//{
//public:
//	string _name; // 姓名
//};
//class Student : virtual public Person
//{
//protected:
//	int _num; //学号
//};
//class Teacher : virtual public Person
//{
//protected:
//	int _id; // 职工编号
//};
//class Assistant : public Student, public Teacher
//{
//protected:
//	string _majorCourse; // 主修课程
//};
//void Test()
//{
//	// 这样会有二义性无法明确知道访问的是哪一个
//	Assistant a;
//	a._name = "peter";
//	// 需要显示指定访问哪个父类的成员可以解决二义性问题，但是数据冗余问题无法解决
//	a.Student::_name = "xxx";
//	a.Teacher::_name = "yyy";
//}


//
//class a
//{
//public:
//	int _a;
//};
//// class b : public a
//class b : virtual public a
//{
//public:
//	int _b;
//};
//// class c : public a
//class c : virtual public a
//{
//public:
//	int _c;
//};
//class d : public b, public c
//{
//public:
//	int _d;
//};
//int main()
//{
//	d d;
//	d.b::_a = 1;
//	d.c::_a = 2;
//	d._b = 3;
//	d._c = 4;
//	d._d = 5;
//
//	b* pb = &d;
//	pb->_a++;
//
//	return 0;
//}
//


//class Person {
//public:
//	 virtual void BuyTicket() { cout << "买票-全价" << endl; }
//	 const char* _name;
//};
//
//
//class Student : public Person {
//public:
//	int _id;
//	virtual void BuyTicket() { cout << "买票-半价" << endl; }
//	/*注意：在重写基类虚函数时，派生类的虚函数在不加virtual关键字时，虽然也可以构成重写(因
//	为继承后基类的虚函数被继承下来了在派生类依旧保持虚函数属性),但是该种写法不是很规范，不建议
//	这样使用*/
//	/*void BuyTicket() { cout << "买票-半价" << endl; }*/
//};
//
//void Func(Person& p)
//{
//	p._name = "lxp";
//	p.BuyTicket();
//}


//int main()
//{
//	Person ps;
//	Student st;
//	Func(ps);
//	Func(st);
//
//	return 0;
//}

//class Person
//{
//public:
//	string _name;
//	int _age;
//};
//
//class Student : public Person
//{
//public:
//	int _id; // 学号
//};
//
//void Test()
//{
//	Student sobj;
//	// 1.子类对象可以赋值给父类对象/指针/引用
//	Person pobj = sobj;
//	Person* pp = &sobj;
//	Person& rp = sobj;
//
//	pobj._age = 2004;
//	pobj._name = "lxp";
//
//
//	pp->_age = 2004;
//	pp->_name = "djm";
//
//	rp._age = 2004;
//	rp._name = "wlt";
//
//
//
//	//2.基类对象不能赋值给派生类对象
//	//sobj = pobj;
//
//	// 3.基类的指针可以通过强制类型转换赋值给派生类的指针
//	//pp = &sobj
//	//Student* ps1 = (Student*)pp; // 这种情况转换时可以的。
//	//ps1->_No = 10;
//
//	//pp = &pobj;
//	//Student* ps2 = (Student*)pp; // 这种情况转换时虽然可以，但是会存在越界访问的问题
//	//ps2->_No = 10;
//}
//
//int main()
//{
//	Test();
//	return 0;
//}
//int main()
//{
//	vector<int> v;
//	int n;
//	cin >> n;
//	for (int i = 0;i < n;i++)
//	{
//		int temp = 0;
//		cin >> temp;
//		v.push_back(temp);
//	}
//
//
//	return 0;
//}

//协变
//
//class A {};
//
//class B : public A {};
//
//class Person {
//public:
//	virtual B* f() { return new A; }
//};
//
//class Student : public Person {
//public:
//	virtual A* f() { return new B; }
//};
//
//int main()
//{
//	return 0;
//}

//class A
//{
//public:
//	virtual void func(int val = 1) { std::cout << "A->" << val << std::endl; }
//	virtual void test() { func(); }
//};
//
//class B : public A
//{
//public:
//	void func(int val = 0) { std::cout << "B->" << val << std::endl; }
//};
//
//int main(int argc, char* argv[])
//{
//	A* pa = new A;
//	A* p = new B;
//	pa->test();
//	p->test();
//	return 0;
//}

//class Base {
//public:
//	void func1() { cout << "Base::func1" << endl; }
//	virtual void func2() { cout << "Base::func2" << endl; }
//private:
//	int a;
//};
//class Derive :public Base {
//public:
//	virtual void func1() { cout << "Derive::func1" << endl; }
//	//virtual void func3() { cout << "Derive::func3" << endl; }
//	virtual void func4() { cout << "Derive::func4" << endl; }
//private:
//	int b;
//};
//
//int main()
//{
//	Base* b = new Base;
//	Base* p = new Derive;
//	Derive* d = new Derive;
//	return 0;
//}


class a
{
public:
	virtual void func1()
	{
		cout << "a::func1()" << endl;
	}
	int _a = 0;
};

class b : virtual public a
{
public:
	virtual void func2()
	{
		cout << "b::func2()" << endl;
	}
	int _b = 0;
};

class c : virtual public a
{
public:

	virtual void func3()
	{
		cout << "c::func3()" << endl;
	}
	int _c = 0;
};

class d : public b,public c
{
public:
	virtual void func4()
	{
		cout << "d::func4()" << endl;
	}
	int _d = 0;
};

typedef void(*VFPTR) ();
void PrintVTable(VFPTR vTable[])
{
	// 依次取虚表中的虚函数指针打印并调用。调用就可以看出存的是哪个函数
	cout << " 虚表地址>" << vTable << endl;
	for (int i = 0; vTable[i] != nullptr; ++i)
	{
		printf(" 第%d个虚函数地址 :0X%x,->", i, vTable[i]);
		VFPTR f = vTable[i];
		f();
	}
	cout << endl;
}

int main()
{
	d D;

	return 0;
}